﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Net;
using System.IO;
using System.Diagnostics;
using Ionic.Zip;
using System.ComponentModel;

using Preferences = LeagueUtils.Preferences;

namespace LeagueToolLauncher
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 
    public partial class MainWindow : Window
    {
        
        WebClient webClient = new WebClient();
        Dictionary<string, string> versionInformation = new Dictionary<string, string>();
        string versionString = "2.2.2";
        Process leagueOverlayProcess;
        bool downloadingUpdater = false;

        BackgroundWorker initialLoadThread;
        public bool disclaimerAccepted = false;
        public bool preferencesLoaded = false;
        public bool heroDataBackedup = true;
        List<string> stopwatch = new List<string>();

        public MainWindow()
        {
            try
            {
                System.Diagnostics.Debug.WriteLine("~~~~~~~~~~~~~ Tool Started ~~~~~~~~~~~~~");
                InitializeComponent();
                versionLbl.Content = versionString;
                Label l = new Label();
                l.FontFamily = new FontFamily("Miramonte");
                l.FontSize = 16;
                l.Foreground = new SolidColorBrush(Colors.White);
                l.Content = "Configuration in process...";
                l.Width = this.Width;
                l.Height = this.Height;
                l.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center;
                l.VerticalContentAlignment = System.Windows.VerticalAlignment.Center;
                this.Content = l;

                if (File.Exists("images/LeagueTools.png"))
                    this.Background = new ImageBrush(new BitmapImage(new Uri(BaseUriHelper.GetBaseUri(this), "images/LeagueTools.png")));

                initialLoadThread = new BackgroundWorker();
                initialLoadThread.DoWork += new DoWorkEventHandler(initialLoadThread_DoWork);
                initialLoadThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(initialLoadThread_RunWorkerCompleted);
                initialLoadThread.RunWorkerAsync();
            }
            catch (Exception e)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + e.Source + "): " + e.Message + "\n" + e.StackTrace);
                throw;
            }
        }


        /*
         * This is the main loop for the league tool launcher, It checks to see if all variables are loaded
         * If not it loads them, for a first time run it gets the user to select the location of the lol.launcher.exe
         * then it shows the disclaimer.
         */ 
        void initialLoadThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                this.Content = mainCanvas;
                if (!preferencesLoaded)
                {
                    if (Preferences.Load())
                    {
                        preferencesLoaded = true;
                        disclaimerAccepted = Preferences.disclaimerAccepted;
                    }
                }
                if (!preferencesLoaded)
                {
                    System.Windows.Forms.OpenFileDialog dlg = new System.Windows.Forms.OpenFileDialog();
                    dlg.Title = "Select the League of Legends executable (lol.launcher.exe)";
                    dlg.Filter = "exe Files (*.exe)|*.EXE|All Files (*.*)|*.*";
                    string LeagueDirectory = "";
                    if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        try
                        {
                            if (dlg.FileName.Substring(dlg.FileName.LastIndexOf("\\") + 1).Contains("lol.launcher.exe"))
                                Preferences.leagueFolder = LeagueDirectory = dlg.FileName.Substring(0, dlg.FileName.LastIndexOf("\\"));
                        }
                        catch { }
                    }
                    Preferences.Save();
                    if (Preferences.Load())
                    {
                        preferencesLoaded = true;
                        disclaimerAccepted = Preferences.disclaimerAccepted;
                    }
                }
                if (preferencesLoaded && !disclaimerAccepted)
                {
                    Disclaimer disclaimer = new Disclaimer(this)
                    {
                        Visibility = Visibility.Visible,
                        Top = this.Top + 110,
                        Left = this.Left + 55
                    };
                    return;
                }
                if (!disclaimerAccepted && !preferencesLoaded)
                {
                    //load failed...
                    new LeagueOverlay.ScriptControl(null).log("[ERROR] : Load failed. DisclaimerAccepted:" + disclaimerAccepted + " PreferencesLoaded:" + preferencesLoaded);
                    this.Close();
                }
            }
            catch (Exception error)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + error.Source + "): " + error.Message + "\n" + error.StackTrace);
                throw;
            }
        }

        void initialLoadThread_DoWork(object sender, DoWorkEventArgs e)
        {
            if (!disclaimerAccepted)
            {
                return;
            }
        }

        public void preferenceSetupComplete()
        {
            try
            {
                Preferences.Save();
                preferencesLoaded = true;
                initialLoadThread.RunWorkerAsync();
            }
            catch (Exception e)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + e.Source + "): " + e.Message + "\n" + e.StackTrace);
                throw;
            }
        }

        public void AcceptDisclaimer()
        {
            try
            {
                Preferences.disclaimerAccepted = disclaimerAccepted = true;
                Preferences.Save();
                initialLoadThread.RunWorkerAsync();
            }
            catch (Exception e)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + e.Source + "): " + e.Message + "\n" + e.StackTrace);
                throw;
            }
        }
        
        /*
         * Web updates have been disabled because I don't have access to the repository.
         */
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                webClient.OpenReadAsync(new Uri("http://code.google.com/p/league-tools-revamped/wiki/VersionPage"));
                webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
                webClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(webClient_DownloadDataCompleted);
                webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);

                updateOverlayButtons();
            }
            catch (Exception error)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + e.Source + "): " + error.Message + "\n" + error.StackTrace);
                throw;
            }
        }

        void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            downloadProgressBar.Value = e.ProgressPercentage;
        }

        void  webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            try
            {
                if (e.Error == null)
                {
                    try
                    {
                        StreamReader sr = new StreamReader(e.Result);
                        string pageText = sr.ReadToEnd();
                        string[] ps = pageText.Split("[[[[[".ToCharArray());
                        foreach (string p in ps)
                        {
                            string[] keyAndValue = (p.Split("]]]]]".ToCharArray()))[0].Split('|');
                            if (keyAndValue.Length == 2)
                            {
                                versionInformation[keyAndValue[0]] = keyAndValue[1];
                            }
                        }


                        if (versionInformation["Version"] != versionString)
                        {
                            updateBtn.Visibility = Visibility.Visible;
                        }
                    }
                    catch
                    {
                        System.Diagnostics.Debug.WriteLine("page parse error");
                    }
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("page not found error");
                }
            }
            catch (Exception error)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + error.Source + "): " + error.Message + "\n" + error.StackTrace);
                throw;
            }
        }

        private void openRecItemToolBtn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                RecommendedItemTool.MainWindow mw = new RecommendedItemTool.MainWindow();
                mw.Visibility = System.Windows.Visibility.Visible;
            }
            catch (Exception error)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + e.Source + "): " + error.Message + "\n" + error.StackTrace);
                throw;
            }
        }

        private void startLeagueBtn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Process.Start(LeagueUtils.Preferences.leagueFolder + "\\lol.launcher.exe");
            }
            catch (Exception error)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + e.Source + "): " + error.Message + "\n" + error.StackTrace);
                throw;
            }
        }

        /*
         * Web updates have been disabled because I don't have access to the repository.
         */
        private void updateBtn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                downloadingUpdater = true;
                webClient.DownloadDataAsync(new Uri(versionInformation["UpdaterLink"]));
                updateBtn.Visibility = Visibility.Hidden;
                downloadProgressBar.Visibility = Visibility.Visible;
                downloadProgressLbl.Visibility = Visibility.Visible;
                downloadProgressLbl.Content = "File 1 of 2";
            }
            catch (Exception error)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + e.Source + "): " + error.Message + "\n" + error.StackTrace);
                throw;
            }
        }

        /*
         * Web updates have been disabled because I don't have access to the repository.
         */
       void webClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
        {
            try
            {
                if (e.Error != null)
                {
                    MessageBox.Show("Error: File not found on the server. Please wait and try again.");
                    return;
                }
                if (downloadingUpdater)
                {
                    File.WriteAllBytes("Updater.zip", e.Result);
                    webClient.DownloadDataAsync(new Uri(versionInformation["DownloadLink"]));
                    using (ZipFile zip = ZipFile.Read("Updater.zip"))
                    {
                        zip.ExtractAll("Updater", ExtractExistingFileAction.OverwriteSilently);
                    }
                    File.Delete("Updater.zip");
                    downloadingUpdater = false;
                    downloadProgressLbl.Content = "File 2 of 2";
                }
                else
                {
                    downloadProgressLbl.Content = "Complete";
                    File.WriteAllBytes("Updater\\newVersion.zip", e.Result);
                    try
                    {
                        MessageBox.Show("The launcher will now close and the update will be applied", "Download Complete");
                        Directory.SetCurrentDirectory("Updater");
                        Process.Start("UpdateTool.exe");
                        this.Close();
                    }
                    catch
                    {
                        System.Diagnostics.Debug.WriteLine("something went wrong :'(");
                    }
                }
            }
            catch (Exception error)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + error.Source + "): " + error.Message + "\n" + error.StackTrace);
                throw;
            }
        }


        /*
         * Try catch is to catch the thread access error, this is to be fixed shortly
         */
        public void updateOverlayButtons()
        {
            try
            {
                try
                {
                    if (leagueOverlayProcess == null)
                    {
                        overlayStartBtn.Content = "Disabled";
                        overlayStartBtn.Foreground = new SolidColorBrush(Colors.Red);
                    }
                    else
                    {
                        overlayStartBtn.Content = "Enabled";
                        overlayStartBtn.Foreground = new SolidColorBrush(Colors.LightGreen);
                    }
                }
                catch { }
            }
            catch (Exception e)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + e.Source + "): " + e.Message + "\n" + e.StackTrace);
                throw;
            }
        }

        /*
         * Starts the overlay process, adding an event handler on exit
         */ 
        private void overlayStartBtn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (leagueOverlayProcess == null)
                {
                    leagueOverlayProcess = Process.Start("LeagueOverlay.exe");
                    leagueOverlayProcess.EnableRaisingEvents = true;
                    leagueOverlayProcess.Exited += new EventHandler(leagueOverlayProcess_Exited);
                }
                else
                {
                    try { leagueOverlayProcess.Kill(); }
                    catch (Exception) { }
                    leagueOverlayProcess = null;
                }
                updateOverlayButtons();
            }
            catch (Exception error)
            {
                new LeagueOverlay.ScriptControl(null).log("[ERROR] (" + e.Source + "): " + error.Message + "\n" + error.StackTrace);
                throw;
            }
        }

        /*
         * This catches the overlay process exiting with an op code of 1 (meaning it exited itself)
         * then it restarts the overlay process (to get it ready for the next match)
         */
        void leagueOverlayProcess_Exited(object sender, EventArgs e)
        {
            try
            {
                if (leagueOverlayProcess.ExitCode == 1)
                {
                    leagueOverlayProcess = Process.Start("LeagueOverlay.exe");
                    leagueOverlayProcess.EnableRaisingEvents = true;
                    leagueOverlayProcess.Exited += new EventHandler(leagueOverlayProcess_Exited);
                }
                else
                    leagueOverlayProcess = null;
            }
            catch
            {
                leagueOverlayProcess = null;
                updateOverlayButtons();
            }
            //updateOverlayButtons();
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            if (leagueOverlayProcess != null) // If the overlay process is still running, nuke it.
                leagueOverlayProcess.Kill();
        }

        /*
         * Restore file button, this runs the LeagueUtils.FileRestore utility
         */
        private void restoreFiles_Click(object sender, RoutedEventArgs e)
        {
            MessageBoxResult dlgResult = MessageBox.Show("Warning:\nThis will restore ALL the files in your League of Legends folder to their original state, "+
            "including Item Builds, Champion Skills, and whatever else League Tools may have changed.","Restore Files?", MessageBoxButton.OKCancel);
            if (dlgResult == MessageBoxResult.OK)
            {
                LeagueUtils.FileRepair.RepairFilesRecursive(Preferences.leagueFolder);
                MessageBox.Show("File repair complete.");
            }
            else
                MessageBox.Show("File repair cancelled, the files that have been altered will remain.");
        }


        /*
         *  This is a rudimentary skin installer, The user selects the .skn file (for now) in the folder of the new skin they want to install.
         *  It then finds the matching champion .skn file and navigates back to find the base champion folder.
         *  Then it recursively finds all files in the new skin folder and replaces the matching file in the found champion folder.
         */
        private void skinInstall_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.OpenFileDialog dlg = new System.Windows.Forms.OpenFileDialog();
            dlg.Title = "Select the skin file in the new skin folder.";
            dlg.Filter = "LoL Skin Files (*.skn)|*.SKN|All Files (*.*)|*.*";
            string skinDirectory = "";
            string FileLocation = "";
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    skinDirectory = dlg.FileName.Substring(0, dlg.FileName.LastIndexOf("\\"));
                    FileLocation = LeagueUtils.FileFinder.findFile(dlg.FileName.Substring(dlg.FileName.LastIndexOf("\\") + 1), Preferences.leagueFolder)[0];
                    FileLocation = FileLocation.Substring(0, FileLocation.LastIndexOf("\\"));
                    MessageBoxResult dlgResult = MessageBox.Show("Warning:\nThis will install the [" + skinDirectory.Substring(skinDirectory.LastIndexOf("\\") + 1) +
                    "] skin into:\n" + FileLocation, "Install Skin?", MessageBoxButton.OKCancel);
                    if (dlgResult == MessageBoxResult.OK)
                    {
                        List<string> result = new List<string>();
                        Stack<string> stack = new Stack<string>();
                        stack.Push(skinDirectory);
                        while (stack.Count > 0)
                        {
                            string dir = stack.Pop();
                            try
                            {
                                result.AddRange(Directory.GetFiles(dir, "*.*"));
                                foreach (string dn in Directory.GetDirectories(dir))
                                    stack.Push(dn);
                            }
                            catch { }
                        }
                        foreach (string file in result)
                        {
                            try
                            {
                                string newFilePath = LeagueUtils.FileFinder.findFile(file.Substring(file.LastIndexOf("\\") + 1), Preferences.leagueFolder)[0];
                                LeagueUtils.FileRepair.BackupFile(newFilePath);
                                File.Copy(file, newFilePath, true);
                            }
                            catch
                            {
                                MessageBox.Show("Error:\n\n An error occured processing:\n" + file + " \nPerhaps renaming the file will fix it.", "Install Skin?");
                                break;
                            }
                            if (file == result[result.Count - 1])
                                MessageBox.Show("The [" + skinDirectory.Substring(skinDirectory.LastIndexOf("\\") + 1) + "] skin has been sucessfully installed", "Skin Install Complete.");
                        }

                    }
                }
                catch{  MessageBox.Show("An error occured while trying to install the skin.", "Error"); }
            }

        }

        private void addonButton_Click(object sender, RoutedEventArgs e)
        {
            AddonBox disclaimer = new AddonBox(this)
            {
                Visibility = Visibility.Visible,
                Top = this.Top + 110,
                Left = this.Left + 55
            };
            return;
        }
    }
}
